package com.bojiu.lawsearch.lawsearch.controller;

import com.bojiu.lawsearch.lawsearch.mapper.WechatUserMapper;
import com.bojiu.lawsearch.lawsearch.model.Admin;
import com.bojiu.lawsearch.lawsearch.model.WechatUser;
import com.bojiu.lawsearch.lawsearch.service.AdminService;
import com.bojiu.lawsearch.lawsearch.service.WechatUserService;
import com.bojiu.lawsearch.lawsearch.task.TaskInit;
import com.bojiu.lawsearch.lawsearch.util.*;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @author: afdiao
 * @Date：2020/2/29 16:34
 * @Description:
 */
@Api(description = "人员登录相关接口")
@Controller
@Slf4j
public class LoginController {

    @Autowired
    WechatUserMapper wechatUserMapper;

    @Autowired
    HttpUtil httpUtil;

//    @Autowired
//    StringRedisTemplate stringRedisTemplate;

    @Autowired
    WechatUserService wechatUserService;

    @Autowired
    AdminService adminService;

    @Autowired
    AuthorizationHandle authorizationHandle;

    @Autowired
    MsgUtil msgUtil;

    /**
     * 网页获取扫面二维码链接
     *
     * @return
     */
    @GetMapping("getWebLogin")
    public String getWebLoginUrl() {
        String url = String.format(Constances.WEBLOGIN_URL, Constances.COMPONENT_APPID, "http://www.qiangui51.cn/lawsearch/getWebCode");
        return "redirect:" + url;
    }

    /**
     * 根据code获取人员信息判断是否注册
     * 链接200  人员已注册  登录附带token
     * 100 人员未注册
     * 300 请求失败
     * 400 该人员已经被删除禁止访问
     *
     * @param code
     * @return
     */
    @GetMapping("getWebCode")
    public String getWebCode(String code, RedirectAttributes redirectAttributes) {
        try {
            String url = String.format(Constances.WEB_ACCESSTOKEN, Constances.COMPONENT_APPID, Constances.COMPONENT_APPSECRET, code);
            JsonObject jsonObject = httpUtil.doGet(url);
            log.debug("网页端明细:{}", jsonObject);
            String unionid = jsonObject.get("unionid").getAsString();
            String openid = jsonObject.get("openid").getAsString();
            String access_token = jsonObject.get("access_token").getAsString();
            //判断人员是否已经注册
            WechatUser exitUser = wechatUserService.exitUser(unionid);
            if (exitUser != null) {
                if (exitUser.getIs_deleted() == 1) {
                    //人员已经删除
                    return "redirect:" + Constances.USER_INDEX_URL + "?code=400";
                }
                //已经注册 登录获取token返200跳转
                String sign = wechatUserService.refreshLoginTime(exitUser.getId());
                redirectAttributes.addAttribute("sign", sign);
                return "redirect:" + Constances.USER_INDEX_URL + "?code=200";
            }

            log.debug("人员未注册，开始获取人员信息");
            String userInfoUrl = String.format(Constances.WEB_USERINFO, access_token, openid);
            log.debug("userInfo url is:{}", userInfoUrl);
            JsonObject userInfoObj = httpUtil.doGet(userInfoUrl);
            log.debug("userInfoObj is :{}", userInfoObj);
            String nickname = userInfoObj.get("nickname").getAsString();
            int sex = userInfoObj.get("sex").getAsInt();
            String headimgurl = userInfoObj.get("headimgurl").getAsString();
            if (StringUtils.isEmpty(nickname) || StringUtils.isEmpty(headimgurl)) {
                log.debug("人员信息为空，userInfo is：{}", userInfoObj);
                return "redirect:" + Constances.USER_INDEX_URL + "?code=300";
            }
            TaskInit.wechatInfo.put(unionid, userInfoObj.toString());
//            String redisKey = RedisUtil.getKeyBy3(RedisKey.PROJECT, RedisKey.WECHAT_USERINFO, unionid);
//            stringRedisTemplate.opsForValue().set(redisKey, userInfoObj.toString());
//            stringRedisTemplate.expire(redisKey, 30, TimeUnit.MINUTES);
            //人员未注册 生成token
            JsonObject tokenObj = new JsonObject();
            tokenObj.addProperty("unionid", unionid);
            String encrypt = EncryptUtil.encrypt(tokenObj.toString());
            redirectAttributes.addAttribute("sign", encrypt);
            log.debug("sign is :{}", encrypt);
            log.debug("开始跳转。。。。。。。。。。。。。。。。");
            return "redirect:" + Constances.USER_INDEX_URL + "?code=100";
        } catch (Exception e) {
            log.error("error to getWebCode,error is :{}", e);
            return "redirect:" + Constances.USER_INDEX_URL + "?code=300";
        }
    }

    @GetMapping("test")
    public String test() {
        return "redirect:" + Constances.USER_INDEX_URL + "?code=100";
    }

    /**
     * 公众号推广地址
     *
     * @return
     */
    @GetMapping("gzlogin")
    public String getCode() {
        String url = String.format(Constances.CODE_URL, Constances.APPID, "http://www.qiangui51.cn/lawsearch/getGzCode?extend=123");
        log.debug("get code url is :{}", url);
        return "redirect:" + url;
    }

    @GetMapping("shareLogin")
    public String shareLogin(String extend) {
        String url = String.format(Constances.CODE_URL, Constances.APPID, "http://www.qiangui51.cn/lawsearch/getGzCode?extend=" + extend);
        log.debug("get code url is :{}", url);
        return "redirect:" + url;
    }


    @GetMapping("getGzCode")
    public String getGzCode(String code, String extend, RedirectAttributes redirectAttributes) {
        try {
            String url = String.format(Constances.OPENID_URL, Constances.APPID, Constances.APPSECRET, code);
            JsonObject jsonObject = httpUtil.doGet(url);
            log.debug("公众号明细：{}", jsonObject);
            String unionid = jsonObject.get("unionid").getAsString();
            String openid = jsonObject.get("openid").getAsString();
            String access_token = jsonObject.get("access_token").getAsString();
            //判断人员是否已经注册
            WechatUser exitUser = wechatUserService.exitUser(unionid);
            if (exitUser != null) {
                if (exitUser.getIs_deleted() == 1) {
                    //人员已经删除
                    return "redirect:" + Constances.GZ_RESULT_HTML + "?code=400";
                }
                //已经注册 登录获取token返200跳转
                redirectAttributes.addAttribute("unionid", unionid);
                return "redirect:" + Constances.GZ_SHARE_HTML;
            }

            //获取人员明细后跳转注册页面
            String userInfoUrl = String.format(Constances.WEB_USERINFO, access_token, openid);
            log.debug("userInfo url is:{}", userInfoUrl);
            JsonObject userInfoObj = httpUtil.doGet(userInfoUrl);
            log.debug("userInfoObj is :{}", userInfoObj);
            String nickname = userInfoObj.get("nickname").getAsString();
            int sex = userInfoObj.get("sex").getAsInt();
            String headimgurl = userInfoObj.get("headimgurl").getAsString();
            if (StringUtils.isEmpty(nickname) || StringUtils.isEmpty(headimgurl)) {
                log.debug("人员信息为空，userInfo is：{}", userInfoObj);
                return "redirect:" + Constances.GZ_INDEX_HTML + "?code=300";
            }
            TaskInit.wechatInfo.put(unionid, userInfoObj.toString());
//            String redisKey = RedisUtil.getKeyBy3(RedisKey.PROJECT, RedisKey.WECHAT_USERINFO, unionid);
//            stringRedisTemplate.opsForValue().set(redisKey, userInfoObj.toString());
//            stringRedisTemplate.expire(redisKey, 30, TimeUnit.MINUTES);

            redirectAttributes.addAttribute("unionid", unionid);
            redirectAttributes.addAttribute("extend", extend);
            return "redirect:" + Constances.GZ_INDEX_HTML;
        } catch (Exception e) {
            log.error("error to getWebCode,error is :{}", e);
            return "redirect:" + Constances.GZ_RESULT_HTML + "?code=100";
        }
    }

    /**
     * 用户注册
     *
     * @param wechatUser
     * @param errors
     * @return
     */
    @ApiOperation(value = "前台用户注册", notes = "用户注册")
    @ApiImplicitParam(name = "sign", required = false)
    @ApiResponses({
            @ApiResponse(code = 200, message = "登录成功，返回人员信息", response = WechatUser.class),
            @ApiResponse(code = 1900, message = "手机验证码错误"),
            @ApiResponse(code = 1500, message = "人员已经注册"),
            @ApiResponse(code = 1300, message = "手机号码已注册"),
            @ApiResponse(code = 400, message = "token过期，重试"),
            @ApiResponse(code = 100, message = "请求失败"),
    })
    @PostMapping("register")
    @ResponseBody
    public JsonResult register(@Valid @RequestBody WechatUser wechatUser, Errors errors, HttpServletRequest request) {
        //校验字段是否为空
        if (errors.hasErrors()) {
            JsonResult jsonResult = UtilTools.handleNullField(errors);
            return jsonResult;
        }
        //判断是否带上unionid
        JsonResult jsonResult = authorizationHandle.webRegisterHandler(request);
        if (!jsonResult.getCode().equals("200")) {
            return jsonResult;
        }

        String unionid = jsonResult.getData().toString();
        wechatUser.setUnionid(unionid);
        JsonResult register = wechatUserService.register(wechatUser);
        return register;
    }

    /**
     * 用户注册
     *
     * @param wechatUser
     * @param errors
     * @return
     */
    @ApiOperation(value = "手机端用户注册", notes = "手机端用户注册")
    @ApiImplicitParam(name = "sign", required = false)
    @ApiResponses({
            @ApiResponse(code = 200, message = "登录成功，返回人员信息", response = WechatUser.class),
            @ApiResponse(code = 1900, message = "手机验证码错误"),
            @ApiResponse(code = 1500, message = "人员已经注册"),
            @ApiResponse(code = 1300, message = "手机号码已注册"),
            @ApiResponse(code = 400, message = "token过期，重试"),
            @ApiResponse(code = 100, message = "请求失败"),
    })
    @PostMapping("gzRegister/{unionid}/{extend}")
    @ResponseBody
    public JsonResult gzRegister(@ApiParam(name = "unionid", value = "用户的unionid", required = true) @PathVariable("unionid") String unionid,@ApiParam(name = "extend", value = "上家的unionid", required = true) @PathVariable("extend") String extend, @Valid @RequestBody WechatUser wechatUser, Errors errors, HttpServletRequest request) {
        //校验字段是否为空
        if (errors.hasErrors()) {
            JsonResult jsonResult = UtilTools.handleNullField(errors);
            return jsonResult;
        }
        wechatUser.setUnionid(unionid);
        wechatUser.setExtendUioinId(extend);
        JsonResult register = wechatUserService.gzRegister(wechatUser);
        return register;
    }

    @ApiOperation(value = "手机号验证码", notes = "用户注册")
    @ApiImplicitParam(name = "sign", required = false)
    @ApiResponses({
            @ApiResponse(code = 200, message = "发送成功"),
            @ApiResponse(code = 100, message = "请求失败，稍后重试"),
    })
    @PostMapping("phoneCode")
    @ResponseBody
    public JsonResult phoneCode(@ApiParam(name = "phone", value = "手机号", required = true) @RequestBody String string) {
        JsonObject jsonObject = new Gson().fromJson(string, JsonObject.class);
        String phone = jsonObject.get("phone").getAsString();
        JsonResult jsonResult = msgUtil.sendMsg(phone, msgUtil.getPhoneCode(phone));
        return jsonResult;
    }

    @ApiOperation(value = "密码登录", notes = "用户使用手机号以及密码登录")
    @ApiResponses({
            @ApiResponse(code = 200, message = "登录成功", response = WechatUser.class),
            @ApiResponse(code = 100, message = "请求失败，稍后重试"),
            @ApiResponse(code = 300, message = "用户名或者密码错误"),
    })
    @PostMapping("loginByPhone")
    @ResponseBody
    public JsonResult loginByPhone(@ApiParam(name = "参数为手机号和密码   phone     password", value = "json格式", required = true) @RequestBody String string) {
        JsonObject jsonObject = new Gson().fromJson(string, JsonObject.class);
        String phone = jsonObject.get("phone").getAsString();
        String password = jsonObject.get("password").getAsString();
        JsonResult result = wechatUserService.loginByPhone(phone, password);
        return result;
    }

    /**
     * 分享
     *
     * @param url
     * @return
     */
    @ApiOperation(value = "分享给下家", notes = "分享")
    @ApiResponses({
            @ApiResponse(code = 200, message = "发送成功"),
            @ApiResponse(code = 100, message = "请求失败，稍后重试"),
    })
    @GetMapping("getShare")
    @ResponseBody
    public JsonResult getShare(@ApiParam(name = "url", value = "当前页面参数", required = true) @RequestParam("url") String url, @ApiParam(name = "extend", value = "分享用户的unionid", required = true) @RequestParam("extend") String extend) {
        Map<String, Object> resultMap = new HashMap<>();
        //获取jsticket
        String nonceStr = UUID.randomUUID().toString();
        long timestamp = System.currentTimeMillis() / 1000;
        String str = "jsapi_ticket=" + TaskInit.jsTicket + "&noncestr=" + nonceStr + "&timestamp=" + timestamp + "&url=" + url;
        String signature = encode(str);
        resultMap.put("appId", Constances.APPID);
        resultMap.put("nonceStr", nonceStr);
        resultMap.put("timestamp", timestamp);
        resultMap.put("url", url);
        resultMap.put("signature", signature);
        resultMap.put("share_url", "http://www.qiangui51.cn/lawsearch/shareLogin?extend=" + extend);


        log.debug("map is :{}", resultMap);
        if (null == resultMap) {
            return new JsonResult(ResultCode.FAIL);
        }
        return new JsonResult(ResultCode.SUCCESS, resultMap);
    }


    public static String encode(String str) {
        if (str == null) {
            return null;
        }
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
            messageDigest.update(str.getBytes());
            return getFormattedText(messageDigest.digest());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static String getFormattedText(byte[] bytes) {
        int len = bytes.length;
        StringBuilder buf = new StringBuilder(len * 2);
        // 把密文转换成十六进制的字符串形式
        for (int j = 0; j < len; j++) {
            buf.append(UtilConstants.HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
            buf.append(UtilConstants.HEX_DIGITS[bytes[j] & 0x0f]);
        }
        return buf.toString();
    }

    /**
     * 后台用户登录
     *
     * @param admin
     * @return
     */
    @ApiOperation(value = "后台人员登录", notes = "管理员以及业务员登录接口")
    @ApiImplicitParam(name = "sign", required = false)
    @ApiResponses({
            @ApiResponse(code = 200, message = "登录成功，返回token", response = JsonResult.class),
            @ApiResponse(code = 300, message = "用户名或者密码错误"),
            @ApiResponse(code = 100, message = "请求失败，稍后重试"),
            @ApiResponse(code = 1200, message = "存在字段为空")
    })
    @PostMapping("backLogin")
    @ResponseBody
    public JsonResult backLogin(@ApiParam(name = "admin", value = "人员的用户名跟密码", required = true) @Valid @RequestBody Admin admin, Errors errors) {
        if (errors.hasErrors()) {
            JsonResult jsonResult = UtilTools.handleNullField(errors);
            return jsonResult;
        }
        JsonResult login = adminService.login(admin.getName(), admin.getPassword());
        return login;
    }

}
